#pragma once
#ifndef SNAPSHOT__PROJECT__HH__
#define SNAPSHOT__PROJECT__HH__

#include <QEnvPrereqs.h>
#include <WeakPtr.h>
#include <unordered_map>
#include "ui_project_page.h"
#include <cassert>
#include <qtreewidget.h>
#include <qtablewidget.h>
#include <SdkVersion.h>

class SnapshotPage;
class SnapshotItem;
class SnapshotProject;

class QTreeWidget;
class QStackedWidget;
class QTreeWidgetItem;

typedef WeakPtr<SnapshotItem> SnapshotItemPtr;
typedef WeakPtr<SnapshotPage> SnapshotPagePtr;
typedef WeakPtr<SnapshotProject> SnapshotProjectPtr;

class SnapshotPage : public QWidget
{
	Ui::ProjectPage ui;
	QStackedWidget * mParent;
	SnapshotItemPtr mProject;

public:
	SnapshotPage( SnapshotItemPtr proj, QStackedWidget * parent = NULL );
	~SnapshotPage();

	bool isOpen() const;
	void open();
	void close();
	void clearContents();

	int index() const;

	void setCurrent( );
	bool isCurrent() const;
	
	int addRow( const StringVector& labels );
	QTableWidget * getTable();
	const QTableWidget * getTable() const;
};

class SnapshotItem
{
	friend class SnapshotProject;
protected:
	String mName, mBranch;
	QTreeWidgetItem * mItem;
	QEnvPath mPath;
	SnapshotPage* mPage;
	bool	mRepository;
	bool	mAdded;
public:
	SnapshotItem ( bool isRepo, const String &name, const QEnvPath &path = QEnvPath(), const String & branch = "" );
	SnapshotItem ( const SnapshotItem &rk );
	virtual ~SnapshotItem ( );
	
	bool isAdded() const{ return mAdded; }
	void setAdded( bool state ){ mAdded = state; }
	SnapshotItem& operator= ( const SnapshotItem &rk );
	
	bool isRepository() const{ return mRepository; }

	void setItem( QTreeWidgetItem * item );
	QTreeWidgetItem * getItem() const;

	void setPage( SnapshotPage* item );
	SnapshotPage* getPage() const;

	const String & getName() const;
	const QEnvPath& getPath() const;
	const String& getBranch() const;

	void setBranch( const String & branch);
	void setName( const String & name);
	void setPath(const QEnvPath& path);
};

class SnapshotProject : public QTreeWidget, public std::unordered_map<std::string, SnapshotItemPtr>
{
	Q_OBJECT

	friend class SnapshotItem;
protected:
	QStackedWidget * mStack;
	QTableWidget * mList;
public:
	typedef SnapshotItem								Item;
	typedef SnapshotItemPtr								ItemPtr;
	typedef SnapshotPage								Page;
	typedef SnapshotPagePtr								PagePtr;
	typedef std::unordered_map<std::string, ItemPtr>	Type;
	
	SnapshotProject (QWidget * parent=NULL);
	SnapshotProject ( const SnapshotProject &rk );
	virtual ~SnapshotProject ();
	
	void refreshSnapshot( );
	void setSnapshotTable( QTableWidget * lst );
	void updateAdded( SnapshotItemPtr ptr );
	void setStackWidget( QStackedWidget * tabs );
	QStackedWidget*getStackWidget();
	const QStackedWidget*getStackWidget() const;
	
	void clear();

	bool hasItem( const String &name ) const;

	SnapshotProject& push_back( Item * itm );
	bool remove( const String &name );
	bool remove( Item * itm );
	
	Lit::Sdk::Version findVersion( )
	{
		Lit::Sdk::Version v;
		std::ifstream ifs( findVersionFile().c_str(), std::ios::in );
		if( !ifs.good() ) return v;
		while( !ifs.eof() )
		{
			std::string ln;
			std::getline( ifs, ln );

			std::stringstream ss(ln);
			std::string word;
			while( ss >> word )
			{
				if( word == "#define" )
				{
					ss >> word;
					if( word == "PROJECT_VERSION_MAJOR" ){ ss >> v.Major; QEnvStatus::addStatus( "\tFound Version Major: " + v.Major, 0, true ); }
					else if( word == "PROJECT_VERSION_MINOR" ){ ss >> v.Minor; QEnvStatus::addStatus( "\tFound Version Minor: " + v.Minor, 0, true ); }
					else if( word == "PROJECT_VERSION_BUILD" ){ ss >> v.Build; QEnvStatus::addStatus( "\tFound Version Build: " + v.Build, 0, true ); }
					else if( word == "PROJECT_VERSION_REVISION" ){ ss >> v.Rev; QEnvStatus::addStatus( "\tFound Version Revision: " + v.Rev, 0, true ); }
				}
			}
		
		}
		ifs.close();
		return v;
	}
	std::string findVersionFile( )
	{
		std::string home = getenv("LIT_HOME");

		QEnvPath ret = QEnvPath(home+"/ProjectVersion.h");
		QEnvStatus::addStatus( "Checking " + ret.path(), 0, true );
		if( ret.exists() ){
			QEnvStatus::addStatus( "\tFound at " + ret.path(), 0, true );
			return ret;
		}
	
		ret = QEnvPath(home+"/CoreLibrary/ProjectVersion.h");
		QEnvStatus::addStatus( "Checking " + ret.path(), 0, true );
		if( ret.exists() ){
			QEnvStatus::addStatus( "\tFound at " + ret.path(), 0, true );
			return ret;
		}

		ret = QEnvPath(home+"/CoreLibrary/include/ProjectVersion.h");
		QEnvStatus::addStatus( "Checking " + ret.path(), 0, true );
		if( ret.exists() ){
			QEnvStatus::addStatus( "\tFound at " + ret.path(), 0, true );
			return ret;
		}

		ret = QEnvPath(home+"/Sdk/CoreLibrary/ProjectVersion.h");
		QEnvStatus::addStatus( "Checking " + ret.path(), 0, true );
		if( ret.exists() ){
			QEnvStatus::addStatus( "\tFound at " + ret.path(), 0, true );
			return ret;
		}

		ret = QEnvPath(home+"/Sdk/CoreLibrary/include/ProjectVersion.h");
		QEnvStatus::addStatus( "Checking " + ret.path(), 0, true );
		if( ret.exists() ){
			QEnvStatus::addStatus( "\tFound at " + ret.path(), 0, true );
			return ret;
		}

		return ret;
	}
protected slots:
	void _showProjectPage( QTreeWidgetItem * ptr, int );
	void _closeProjectPage(int);
	void _projectStateChanged( QTreeWidgetItem * itm, int );
};

#endif